package list;

public class ArrayList<E> {

	/*
	 * public static void main(String[] args){
	 * 
	 * }
	 * 
	 * static <E> void printStats(ArrayList<E> arr){
	 * System.out.println("Array: "+arr);
	 * System.out.println("\tsize: "+arr.size);
	 * System.out.println("\tarray.length:"+arr.array.length); }
	 */

	E[] array;
	int size;

	/**
	 * Creates an array list with the given starting capacity
	 * 
	 * @param starting_size
	 */
	public ArrayList(int startingSize) {
		array = (E[]) new Object[startingSize];
		size = 0;
	}

	/**
	 * Creates an array list with a capacity of 10
	 */
	public ArrayList() {
		this(10);
	}

	/**
	 * Returns the item stored at index
	 * 
	 * @param index
	 * @return
	 */
	public E get(int index) {
		if (index >= size)
			throw new ArrayIndexOutOfBoundsException(index);
		return array[index];
	}

	/**
	 * Sets the item at index
	 * 
	 * @param index
	 * @param item
	 */
	public void set(int index, E item) {
		if (index >= size)
			throw new ArrayIndexOutOfBoundsException(index);
		array[index] = item;
	}

	/**
	 * Appends an item to the end of this list
	 * 
	 * @param item
	 */
	public void add(E item) {
		if (size == array.length) {
			expand();
		}

		array[size] = item;
		size++;
	}

	/**
	 * Removes the element at index and shifts the other elements down.
	 * 
	 * @param index
	 */
	public void remove(int index) {
		if (index >= size)
			throw new ArrayIndexOutOfBoundsException(index);
		for (int i = index; i < size - 1; i++) {
			array[i] = array[i + 1];
		}
		array[size - 1] = null;
		size--;
	}

	/**
	 * Removes the FIRST equality of item in this array. Uses .equals for
	 * comparisons.
	 * 
	 * @param item
	 */
	public void remove(E item) {
		for (int i = 0; i < size; i++) {
			if (array[i].equals(item)) {
				remove(i);
				return;
			}
		}
	}

	/**
	 * Returns whether item is in this list. Uses .equals for comparisons
	 * 
	 * @param item
	 * @return
	 */
	public boolean contains(E item) {
		for (int i = 0; i < size; i++) {
			if (array[i].equals(item)) {
				return true;
			}
		}
		return false;
	}

	public int size() {
		return size;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for (int i = 0; i < size; i++) {
			sb.append(array[i].toString());
			sb.append(", ");
		}
		sb.append("]");
		return sb.toString();

	}

	/**
	 * Returns a copy of this array. Elements are shallow copied.
	 */
	public ArrayList<E> clone() {
		E[] newArray = (E[]) new Object[array.length];
		for (int i = 0; i < array.length; i++) {
			newArray[i] = array[i];
		}
		ArrayList<E> newList = new ArrayList<E>(0);
		newList.array = newArray;
		newList.size = size;
		return newList;
	}

	/**
	 * Doubles the capacity of this array.
	 */
	private void expand() {
		E[] newArray = (E[]) new Object[array.length * 2];
		for (int i = 0; i < array.length; i++) {
			newArray[i] = array[i];
		}
		array = newArray;
	}
}
